package controllers

import (
	"encoding/base64"
	"github.com/kataras/iris"
	"go_oauth2/config"
	"go_oauth2/constant"
	"go_oauth2/utils"
	"strings"
)

type ApiResponseJson struct {
	Status bool        `json:"status"`
	Msg    interface{} `json:"msg"`
	Data   interface{} `json:"data"`
}

func ApiResource(status bool, objects interface{}, msg string) (apiJson *ApiResponseJson) {
	apiJson = &ApiResponseJson{Status: status, Data: objects, Msg: msg}
	return
}

func ApiResourceSuccess(objects interface{}) (apiJson *ApiResponseJson) {
	apiJson = &ApiResponseJson{Status: true, Data: objects, Msg: "success"}
	return
}

func ApiResourceError(msg string) (apiJson *ApiResponseJson) {
	apiJson = &ApiResponseJson{Status: false, Data: nil, Msg: msg}
	return
}

type configClients struct {
	Clients []configClient `toml:"clients"`
}

type configClient struct {
	ClientId     string `toml:"clientId"`
	ClientSecret string `toml:"clientSecret"`
}

/**
 * 校验客户端配置信息是否符合标准
 * @method checkRequestClient
 * @param [iris.Context] context [IRIS上下文]
 */
func CheckRequestClient(context iris.Context) (bool, string) {
	// 首先校验该客户端是否受信任
	// 要求客户端的请求头中有Authorization项
	// 同时该项经过base64解码等于clientId:clientSecret
	authorization := context.GetHeader(constant.Authorization)
	authorizationContent, err := base64.StdEncoding.DecodeString(authorization)
	if len(authorization) == 0 || err != nil {
		// 错误的请求
		context.StatusCode(iris.StatusBadRequest)
		// 没有Authorization项
		// 或者Authorization项不符合规范（无法解析）
		_, _ = context.JSON(ApiResourceError(constant.AuthorizationError))
		return false, ""
	}

	// 然后读取配置文件
	// 将授权的客户端信息都读取出来
	result := configClients{}
	if err := config.Config.Unmarshal(&result); err != nil {
		// 程序内部错误
		context.StatusCode(iris.StatusInternalServerError)
		// 读取配置文件出现错误
		_, _ = context.JSON(ApiResourceError(constant.ReadConfigError))
		return false, ""
	}

	// 判断当前客户端是否授权
	isExist, clientId := inClients(result.Clients, string(authorizationContent))
	if !isExist {
		// 错误的请求
		context.StatusCode(iris.StatusBadRequest)
		// 该客户端未授权
		_, _ = context.JSON(ApiResourceError(constant.ClientAuthorizationError))
		return false, ""
	}

	return true, clientId
}

/**
 * 判断客户端是否符合规则
 * @method inClients
 * @param [[]configClient] clients [所有的客户端]
 * @param [string] authorizationContent [当前客户端]
 */
func inClients(clients []configClient, authorizationContent string) (bool, string) {
	for _, client := range clients {
		clientId := client.ClientId
		clientSecret := client.ClientSecret
		isEqually := utils.CompareInsensitive(
			strings.Join([]string{clientId, ":", clientSecret}, ""),
			authorizationContent)
		if isEqually {
			return true, clientId
		}
	}
	return false, ""
}
